Loading Required Libraries

library(dplyr)
library(tidyr)
library(ggplot2)
library(patchwork)

Reading and Inspecting Data

## old data ##
field_data <- read.csv("~/Remote-sensing/DATA/MF_TreeCensus_Cleaned26082025.csv")
head(field_data)
NA
NA
## new data ##
new_field_data <- read.csv("~/Remote-sensing/DATA/MF_TreeCensus_Cleaned20251002.csv")
head(new_field_data)

Data Validation

OLD Data

#Total amount of data
n_total <- nrow(field_data)

#count distinct tree
#n_tag <- length(unique(field_data$Tag))
n_tag <- n_distinct(field_data$Tag)

#The number of unique (Tag, StemTag) pairs 
n_unique_stem <- nrow(field_data %>% distinct(Tag, StemTag))

n_total
[1] 8568
n_tag
[1] 6505
n_unique_stem
[1] 8535

NEW Data

#Total amount of data
new_n_total <- nrow(new_field_data)

#count distinct tree
#n_tag <- length(unique(field_data$Tag))
new_n_tag <- n_distinct(new_field_data$Tag)

#The number of unique (Tag, StemTag) pairs 
new_unique_stem <- nrow(new_field_data %>% distinct(Tag, StemTag))

new_n_total
[1] 8560
new_n_tag
[1] 6525
new_unique_stem
[1] 8560
## Check for duplicate rows ##
#OLD Data

#Identify rows where (Tag, StemTag) appears more than once
dup_pairs <- field_data %>%
  count(Tag, StemTag, name = "n") %>%
  filter(n > 1)

#View rows with duplicate (Tag, StemTag) pairs 
duplicate_rows <- field_data %>%
  semi_join(dup_pairs, by = c("Tag", "StemTag")) %>%  
  arrange(Tag, StemTag)  
  
duplicate_rows
nrow(duplicate_rows)
[1] 65
## Check for duplicate rows ##
#New Data

#Identify rows where (Tag, StemTag) appears more than once
new_dup_pairs <- new_field_data %>%
  count(Tag, StemTag, name = "n") %>%
  filter(n > 1)

#View rows with duplicate (Tag, StemTag) pairs 
new_duplicate_rows <- new_field_data %>%
  semi_join(new_dup_pairs, by = c("Tag", "StemTag")) %>%  
  arrange(Tag, StemTag)  
  
new_duplicate_rows
nrow(new_duplicate_rows)
[1] 0
#Filter to the first row per group
#OLD Data

df_nodup <- field_data %>%
  group_by(Tag, StemTag) %>%
  slice(1) %>%
  ungroup()

nrow(df_nodup)
[1] 8535
df_nodup
NA
#Filter to the first row per group
#NEW Data
new_df_nodup <- new_field_data %>%
  group_by(Tag, StemTag) %>%
  slice(1) %>%
  ungroup()

nrow(new_df_nodup)
[1] 8560
new_df_nodup
#Check for missing values in each column
#OLD Data
colSums(is.na(df_nodup))
    ExactDate     Plot_name       Quadrat           Tag       StemTag Genus.species            QX            QY            PX 
            0             0             0             0             0             0             0             0             0 
           PY           DBH           HOM          Code 
            0             4            56          6302 
#Check for missing values in each column
#NEW Data
colSums(is.na(new_df_nodup))
    ExactDate     Plot_name       Quadrat           Tag       StemTag Genus_species            QX            QY            PX 
            0             0             0             0             0             0             0             0             0 
           PY           DBH           HOM          Code    Note_Genus 
            0             4            56          1915             0 
#Check rows that have null DBH values
#OLD Data
DBH_na <- df_nodup %>%
  filter(is.na(DBH)) 
head(DBH_na)
NA
#Check rows that have null DBH values
#NEW Data
new_DBH_na <- new_df_nodup %>%
  filter(is.na(DBH)) 


new_stemtag_na <- new_df_nodup %>%
  filter(is.na(StemTag)) 

new_DBH_na
new_stemtag_na

## New Data has no stemtag = 2 rows !!!
# and has no DBH = 4 rows

#CLEAN DATA

#Keep observations with DBH present and DBH ≥ 5
#old data
data_clean <- df_nodup  %>%
  filter(!is.na(DBH) & DBH >= 5)

nrow(data_clean)
[1] 8531
head(data_clean)
#Keep observations with DBH present and DBH ≥ 5 and Stemtag present
#new data

new_data_clean <- new_df_nodup  %>%
  filter(!is.na(DBH) & DBH >= 5 & !is.na(StemTag))

nrow(new_data_clean)
[1] 8556
head(new_data_clean)

VISUALIZATION

#   Identify the species in the dataset 
# OLD DATA #

species_tree <- data_clean %>%
  group_by(Genus.species) %>%
  summarise(count = n())  %>%
  arrange(desc(count))

species_tree

#nrow(species_tree)
#   Identify the species in the dataset 
# New DATA #

new_species_tree <- new_data_clean %>%
  group_by(Genus_species) %>%
  summarise(count = n())  %>%
  arrange(desc(count))

new_species_tree

#nrow(species_tree)
#OLD DATA
# 1) นับจำนวนกิ่งต่อ "ต้น"
stem_count <- data_clean %>%
  group_by(Tag, Genus.species) %>%
  summarise(n_stems = n(), .groups = "drop")

# 2) เลือกเฉพาะต้นที่แตกกิ่ง (มีมากกว่า 1 กิ่ง)
multi_stem <- stem_count %>%
  filter(n_stems > 1)

# 3) นับจำนวน "ต้นที่แตกกิ่ง" ต่อ species
species_multi_count <- multi_stem %>%
  count(Genus.species, sort = TRUE)
  # %>%
  #slice_max(n, n = 12)
species_multi_count
#OLD DATA
species_multi_count <- data_clean %>%
  group_by(Tag, Genus.species) %>%
  summarise(n_stems = n(), .groups = "drop") %>%
  filter(n_stems > 1) %>%
  count(Genus.species, sort = TRUE) 
  #%>%  slice_max(n, n = 12)
species_multi_count

ggplot(species_multi_count, aes(x = reorder(Genus.species, n), y = n)) +
  geom_col(fill = "#26C4B8") +
  coord_flip() +
  labs(
    title = "Number of Multi-stem Trees by Species",
    x = "Species",
    y = "Number of Multi-stem Trees"
  ) +
  theme_minimal(base_size = 12)

# 1) หา Top 12 species (กันซ้ำรายต้นก่อน)
top12_species <- data_clean %>%
  distinct(Tag, Genus.species) %>%
  count(Genus.species, sort = TRUE) %>%
  slice_max(n, n = 12)

# 2) Plot bar chart
ggplot(top12_species, aes(x = reorder(Genus.species, n), y = n)) +
  geom_col(fill = "#26C4B8") +
  coord_flip() +
  labs(
    title = "Top 12 Species by Number of Trees",
    x = "Species",
    y = "Number of Trees"
  ) +
  theme_minimal(base_size = 12)

#NEW DATA
# 1) นับจำนวนกิ่งต่อ "ต้น"
new_stem_count <- new_data_clean %>%
  group_by(Tag, Genus_species) %>%
  summarise(n_stems = n(), .groups = "drop")

# 2) เลือกเฉพาะต้นที่แตกกิ่ง (มีมากกว่า 1 กิ่ง)
new_multi_stem <- new_stem_count %>%
  filter(n_stems > 1)

# 3) นับจำนวน "ต้นที่แตกกิ่ง" ต่อ species
new_species_multi_count <- new_multi_stem %>%
  count(Genus_species, sort = TRUE)

new_species_multi_count
#NEW DATA
new_species_multi_count <- new_data_clean %>%
  group_by(Tag, Genus_species) %>%
  summarise(n_stems = n(), .groups = "drop") %>%
  filter(n_stems > 1) %>%
  count(Genus_species, sort = TRUE)
  # %>% slice_max(n, n = 12)
new_species_multi_count
# ใส่ label ว่าเป็น Old หรือ New
species_multi_count <- species_multi_count %>%
  mutate(Source = "Old")

new_species_multi_count <- new_species_multi_count %>%
  mutate(Source = "New")

# รวมตาราง
combined_multi_count <- bind_rows(
  species_multi_count %>% rename(Species = Genus.species),
  new_species_multi_count %>% rename(Species = Genus_species)
)
library(dplyr)
library(tidyr)
library(ggplot2)
library(stringr)

# 0) ทำความสะอาดชื่อสปีชีส์กันกรณีเว้นวรรค/รูปแบบต่างกัน
combined_multi_count <- combined_multi_count %>%
  mutate(Species = str_squish(Species))

# 1) หา Top 12 จากผลรวม (Old + New)
top12_species <- combined_multi_count %>%
  group_by(Species) %>%
  summarise(Total = sum(n, na.rm = TRUE), .groups = "drop") %>%
  arrange(desc(Total)) %>%
  slice_head(n = 12) %>%
  pull(Species)

# 2) กรองเฉพาะ Top 12 และกำหนดลำดับแกน X ตาม Total (มาก -> น้อย)
species_order <- combined_multi_count %>%
  group_by(Species) %>%
  summarise(Total = sum(n, na.rm = TRUE), .groups = "drop") %>%
  filter(Species %in% top12_species) %>%
  arrange(desc(Total)) %>%
  pull(Species)

combined_top12 <- combined_multi_count %>%
  filter(Species %in% top12_species) %>%
  mutate(Species = factor(Species, levels = species_order)) %>%
  # 3) ให้แต่ละสปีชีส์มีข้อมูล Old และ New อย่างละ 1 แท่ง (ถ้าไม่มี เติม 0)
  complete(Species, Source, fill = list(n = 0))

# กำหนดลำดับ Source = Old ก่อน New
combined_top12 <- combined_top12 %>%
  mutate(Source = factor(Source, levels = c("Old", "New")))

# Plot
ggplot(combined_top12, aes(x = Species, y = n, fill = Source)) +
  geom_col(position = "dodge") +
  labs(
    x = "GenusSpecies",
    y = "Number of multi-stem trees",
    title = "Top 12 species: Old vs New (multi-stem count)"
  ) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "top"
  )

ymax <- max(combined_top12$n, na.rm = TRUE)

ggplot(combined_top12, aes(x = Species, y = n, fill = Source)) +
  geom_col(position = "dodge") +
  scale_y_continuous(
    breaks = seq(0, ymax, by = 50),      # กำหนดช่วงทุก 50
    labels = scales::comma               # ใส่ comma เช่น 1,000
  ) +
  labs(
    x = "GenusSpecies",
    y = "Number of multi-stem trees",
    title = "Top 12 species: Old vs New (multi-stem count)"
  ) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "top"
  )

#   Bar plot of total tree counts by species
# OLD data

ggplot(species_tree, aes(x = reorder(Genus.species, count), y = count)) +
  geom_col(fill = "steelblue") +
  coord_flip() +  # flip the axis
  labs(title = "Tree count by species ",
       x = "GenusSpecies",
       y = "number of tree") +
  theme_minimal()

#   Bar plot of total tree counts by species
# New data

ggplot(new_species_tree, aes(x = reorder(Genus_species, count), y = count)) +
  geom_col(fill = "steelblue") +
  coord_flip() +  # flip the axis
  labs(title = "Tree count by species ",
       x = "GenusSpecies",
       y = "number of tree") +
  theme_minimal()

#Bar plot of the 12 most abundant species 
#OLD data

top12 <- species_tree %>% slice_head(n = 12)

ggplot(top12, aes(x = reorder(Genus.species, count), y = count)) +
  geom_col(fill = "forestgreen") +
  coord_flip() +
  labs(title = "Top 12 Most common GenusSpecies OLD data ",
       x = "GenusSpecies",
       y = "number of tree") +
  theme_minimal()

#Bar plot of the 12 most abundant species 
#New Data

top12 <- new_species_tree %>% slice_head(n = 12)

ggplot(top12, aes(x = reorder(Genus_species, count), y = count)) +
  geom_col(fill = "forestgreen") +
  coord_flip() +
  labs(title = "Top 12 Most common GenusSpecies New Data",
       x = "GenusSpecies",
       y = "number of tree") +
  theme_minimal()

DBH Distribution by species

DBH for tree level

#Calculate tree-level DBH
# OLD data
dbh_tree <- data_clean %>%
  filter(!is.na(DBH)) %>%             
  group_by(Tag, Genus.species) %>%     
  summarise(DBH_tree = sqrt(sum(DBH^2)), .groups = "drop")
dbh_tree
#Calculate tree-level DBH
# New data
new_dbh_tree <- new_data_clean %>%
  filter(!is.na(DBH)) %>%             
  group_by(Tag, Genus_species) %>%     
  summarise(DBH_tree = sqrt(sum(DBH^2)), .groups = "drop")
new_dbh_tree
# OLD data
# Prepare a list of the top 12 species at the tree level
distribution_species_tree <- dbh_tree %>%
  count(Genus.species, sort = TRUE) %>%
  slice_max(n, n = 12) %>%
  pull(Genus.species)

# Arrange species in ascending order of abundance
species_order_tree <- dbh_tree %>%
  count(Genus.species, sort = TRUE) %>%
  filter(Genus.species %in% distribution_species_tree) %>%
  pull(Genus.species)  %>%
  rev()

# boxplot (tree level)
ggplot(
  dbh_tree %>%
    filter(Genus.species %in% distribution_species_tree) %>%
    mutate(Genus.species = factor(Genus.species, levels = species_order_tree)),
  aes(x = Genus.species, y = DBH_tree)
) +
  geom_boxplot(fill = "#26C4B8", outlier.color = "#E6B800", outlier.size = 1) +
  coord_flip() +
  labs(
    title = "Tree-level DBH Distribution (Top 12 Species) OLD DATA",
    x = "GenusSpecies",
    y = "DBH (cm)"
  ) +
  theme_minimal(base_size = 12)

# New Data
# Prepare a list of the top 12 species at the tree level
distribution_new_species_tree <- new_dbh_tree %>%
  count(Genus_species, sort = TRUE) %>%
  slice_max(n, n = 12) %>%
  pull(Genus_species)

# Arrange species in ascending order of abundance
new_species_order_tree <- new_dbh_tree %>%
  count(Genus_species, sort = TRUE) %>%
  filter(Genus_species %in% distribution_new_species_tree) %>%
  pull(Genus_species)  %>%
  rev()

# boxplot (tree level)
ggplot(
  new_dbh_tree %>%
    filter(Genus_species %in% distribution_new_species_tree) %>%
    mutate(Genus_species = factor(Genus_species, levels = new_species_order_tree)),
  aes(x = Genus_species, y = DBH_tree)
) +
  geom_boxplot(fill = "#E75480", outlier.color = "#E6B800", outlier.size = 1) +
  coord_flip() +
  labs(
    title = "Tree-level DBH Distribution (Top 12 Species) NEW DATA",
    x = "GenusSpecies",
    y = "DBH (cm)"
  ) +
  theme_minimal(base_size = 12)

DBH stem level

OLD data

#The 12 species with the highest number of trees 
distribution_species_stem <- data_clean %>%
  distinct(Tag, Genus.species) %>%         
  count(Genus.species, sort = TRUE) %>% 
  slice_max(n, n = 12) %>%   
  pull(Genus.species)

#   Sequence of the 12 species for plotting, sorted in ascending order of abundance
species_order_stem <- data_clean %>%
  distinct(Tag, Genus.species) %>%
  count(Genus.species, sort = TRUE) %>%
  filter(Genus.species %in% distribution_species_stem) %>%
  pull(Genus.species) %>%
  rev()
# Box plot  for Stem level

ggplot(
  data_clean %>%
    filter(Genus.species %in% distribution_species_stem) %>%
    mutate(Genus.species = factor(Genus.species, levels = species_order_stem)),
  aes(x = Genus.species, y = DBH)
) +
  geom_boxplot(fill = "#26C4B8", outlier.color = "#E6B800", outlier.size = 1) +
  coord_flip() +
  labs(
    title = "Stem-level DBH Distribution (Top 12 Species) OLD DATA",
    x = "GenusSpecies",
    y = "DBH (cm)"
  ) +
  theme_minimal(base_size = 12)

#New data

#The 12 species with the highest number of trees 
new_distribution_species_stem <- new_data_clean %>%
  distinct(Tag, Genus_species) %>%         
  count(Genus_species, sort = TRUE) %>% 
  slice_max(n, n = 12) %>%   
  pull(Genus_species)

#   Sequence of the 12 species for plotting, sorted in ascending order of abundance
new_species_order_stem <- new_data_clean %>%
  distinct(Tag, Genus_species) %>%
  count(Genus_species, sort = TRUE) %>%
  filter(Genus_species %in% new_distribution_species_stem) %>%
  pull(Genus_species) %>%
  rev()
# Box plot  for Stem level

ggplot(
  new_data_clean %>%
    filter(Genus_species %in% new_distribution_species_stem) %>%
    mutate(Genus_species = factor(Genus_species, levels = new_species_order_stem)),
  aes(x = Genus_species, y = DBH)
) +
  geom_boxplot(fill = "#E75480", outlier.color = "#E6B800", outlier.size = 1) +
  coord_flip() +
  labs(
    title = "Stem-level DBH Distribution (Top 12 Species) NEW DATA",
    x = "GenusSpecies",
    y = "DBH (cm)"
  ) +
  theme_minimal(base_size = 12)

#Density plot of DBH by Tree-level
#OLD data
species_order_tree <- dbh_tree %>%
  count(Genus.species, sort = TRUE) %>%
  slice_max(n, n = 12) %>%
  pull(Genus.species)

ggplot(
  dbh_tree %>%
    filter(Genus.species %in% species_order_tree) %>%
    mutate(Genus.species = factor(Genus.species, levels = species_order_tree)),
  aes(x = DBH_tree)
) +
  geom_density(fill = "#26C4B8", alpha = 0.6) +
  facet_wrap(~ Genus.species, scales = "free") + 
  labs(title = "Tree-level DBH Density (Top 12 Species) OLD DATA",
       x = " DBH (cm)", y = "Density") +
  theme_minimal(base_size = 10) +
  theme(legend.position = "none")

#Density plot of DBH by Tree-level
#NEW data
new_species_order_tree <- new_dbh_tree %>%
  count(Genus_species, sort = TRUE) %>%
  slice_max(n, n = 12) %>%
  pull(Genus_species)

ggplot(
  new_dbh_tree %>%
    filter(Genus_species %in% new_species_order_tree) %>%
    mutate(Genus_species = factor(Genus_species, levels = new_species_order_tree)),
  aes(x = DBH_tree)
) +
  geom_density(fill = "#E75480", alpha = 0.6) +
  facet_wrap(~ Genus_species, scales = "free") + 
  labs(title = "Tree-level DBH Density (Top 12 Species) NEW DATA",
       x = " DBH (cm)", y = "Density") +
  theme_minimal(base_size = 10) +
  theme(legend.position = "none")

#Density plot of DBH by Stem-level
#OLD data
species_order_stem <- data_clean %>%
  distinct(Tag, Genus.species) %>%
  count(Genus.species, sort = TRUE) %>%
  filter(Genus.species %in% distribution_species_stem) %>%
  pull(Genus.species)


ggplot(
  data_clean %>%
    filter(Genus.species %in% distribution_species_stem) %>%
    mutate(Genus.species = factor(Genus.species, levels = species_order_stem)),
  aes(x = DBH, fill = Genus.species)
) +
  geom_density(fill = "#26C4B8", alpha = 0.6) +
  facet_wrap(~ Genus.species, scales = "free") +
  labs(
    title = "Stem-level DBH Density (Top 12 Species) OLD DATA",
    x = "DBH (cm)",
    y = "Density"
  ) +
  theme_minimal(base_size = 10) +
  theme(legend.position = "none")

#Density plot of DBH by Stem-level
#NEW data
new_species_order_tree <- new_data_clean %>%
  distinct(Tag, Genus_species) %>%
  count(Genus_species, sort = TRUE) %>%
  filter(Genus_species %in% distribution_new_species_tree) %>%
  pull(Genus_species)


ggplot(
  new_data_clean %>%
    filter(Genus_species %in% distribution_new_species_tree) %>%
    mutate(Genus_species = factor(Genus_species, levels = new_species_order_tree)),
  aes(x = DBH, fill = Genus_species)
) +
  geom_density(fill = "#E75480", alpha = 0.6) +
  facet_wrap(~ Genus_species, scales = "free") +
  labs(
    title = "Stem-level DBH Density (Top 12 Species) NEW DATA",
    x = "DBH (cm)",
    y = "Density"
  ) +
  theme_minimal(base_size = 10) +
  theme(legend.position = "none")

LS0tCnRpdGxlOiAiRGF0YSBDbGVhbmluZyBhbmQgQW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIExvYWRpbmcgUmVxdWlyZWQgTGlicmFyaWVzCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBhdGNod29yaykKYGBgCgojIyBSZWFkaW5nIGFuZCBJbnNwZWN0aW5nIERhdGEKCmBgYHtyfQojIyBvbGQgZGF0YSAjIwpmaWVsZF9kYXRhIDwtIHJlYWQuY3N2KCJ+L1JlbW90ZS1zZW5zaW5nL0RBVEEvTUZfVHJlZUNlbnN1c19DbGVhbmVkMjYwODIwMjUuY3N2IikKaGVhZChmaWVsZF9kYXRhKQoKCmBgYAoKYGBge3J9CiMjIG5ldyBkYXRhICMjCm5ld19maWVsZF9kYXRhIDwtIHJlYWQuY3N2KCJ+L1JlbW90ZS1zZW5zaW5nL0RBVEEvTUZfVHJlZUNlbnN1c19DbGVhbmVkMjAyNTEwMDIuY3N2IikKaGVhZChuZXdfZmllbGRfZGF0YSkKYGBgCgojIyBEYXRhIFZhbGlkYXRpb24KIyBPTEQgRGF0YSAKCmBgYHtyfQojVG90YWwgYW1vdW50IG9mIGRhdGEKbl90b3RhbCA8LSBucm93KGZpZWxkX2RhdGEpCgojY291bnQgZGlzdGluY3QgdHJlZQojbl90YWcgPC0gbGVuZ3RoKHVuaXF1ZShmaWVsZF9kYXRhJFRhZykpCm5fdGFnIDwtIG5fZGlzdGluY3QoZmllbGRfZGF0YSRUYWcpCgojVGhlIG51bWJlciBvZiB1bmlxdWUgKFRhZywgU3RlbVRhZykgcGFpcnMgCm5fdW5pcXVlX3N0ZW0gPC0gbnJvdyhmaWVsZF9kYXRhICU+JSBkaXN0aW5jdChUYWcsIFN0ZW1UYWcpKQoKbl90b3RhbApuX3RhZwpuX3VuaXF1ZV9zdGVtCmBgYAoKIyMgTkVXIERhdGEgIyMKYGBge3J9CiNUb3RhbCBhbW91bnQgb2YgZGF0YQpuZXdfbl90b3RhbCA8LSBucm93KG5ld19maWVsZF9kYXRhKQoKI2NvdW50IGRpc3RpbmN0IHRyZWUKI25fdGFnIDwtIGxlbmd0aCh1bmlxdWUoZmllbGRfZGF0YSRUYWcpKQpuZXdfbl90YWcgPC0gbl9kaXN0aW5jdChuZXdfZmllbGRfZGF0YSRUYWcpCgojVGhlIG51bWJlciBvZiB1bmlxdWUgKFRhZywgU3RlbVRhZykgcGFpcnMgCm5ld191bmlxdWVfc3RlbSA8LSBucm93KG5ld19maWVsZF9kYXRhICU+JSBkaXN0aW5jdChUYWcsIFN0ZW1UYWcpKQoKbmV3X25fdG90YWwKbmV3X25fdGFnCm5ld191bmlxdWVfc3RlbQpgYGAKCgpgYGB7cn0KIyMgQ2hlY2sgZm9yIGR1cGxpY2F0ZSByb3dzICMjCiNPTEQgRGF0YQoKI0lkZW50aWZ5IHJvd3Mgd2hlcmUgKFRhZywgU3RlbVRhZykgYXBwZWFycyBtb3JlIHRoYW4gb25jZQpkdXBfcGFpcnMgPC0gZmllbGRfZGF0YSAlPiUKICBjb3VudChUYWcsIFN0ZW1UYWcsIG5hbWUgPSAibiIpICU+JQogIGZpbHRlcihuID4gMSkKCiNWaWV3IHJvd3Mgd2l0aCBkdXBsaWNhdGUgKFRhZywgU3RlbVRhZykgcGFpcnMgCmR1cGxpY2F0ZV9yb3dzIDwtIGZpZWxkX2RhdGEgJT4lCiAgc2VtaV9qb2luKGR1cF9wYWlycywgYnkgPSBjKCJUYWciLCAiU3RlbVRhZyIpKSAlPiUgIAogIGFycmFuZ2UoVGFnLCBTdGVtVGFnKSAgCiAgCmR1cGxpY2F0ZV9yb3dzCm5yb3coZHVwbGljYXRlX3Jvd3MpCmBgYAoKCmBgYHtyfQojIyBDaGVjayBmb3IgZHVwbGljYXRlIHJvd3MgIyMKI05ldyBEYXRhCgojSWRlbnRpZnkgcm93cyB3aGVyZSAoVGFnLCBTdGVtVGFnKSBhcHBlYXJzIG1vcmUgdGhhbiBvbmNlCm5ld19kdXBfcGFpcnMgPC0gbmV3X2ZpZWxkX2RhdGEgJT4lCiAgY291bnQoVGFnLCBTdGVtVGFnLCBuYW1lID0gIm4iKSAlPiUKICBmaWx0ZXIobiA+IDEpCgojVmlldyByb3dzIHdpdGggZHVwbGljYXRlIChUYWcsIFN0ZW1UYWcpIHBhaXJzIApuZXdfZHVwbGljYXRlX3Jvd3MgPC0gbmV3X2ZpZWxkX2RhdGEgJT4lCiAgc2VtaV9qb2luKG5ld19kdXBfcGFpcnMsIGJ5ID0gYygiVGFnIiwgIlN0ZW1UYWciKSkgJT4lICAKICBhcnJhbmdlKFRhZywgU3RlbVRhZykgIAogIApuZXdfZHVwbGljYXRlX3Jvd3MKbnJvdyhuZXdfZHVwbGljYXRlX3Jvd3MpCmBgYAoKCmBgYHtyfQojRmlsdGVyIHRvIHRoZSBmaXJzdCByb3cgcGVyIGdyb3VwCiNPTEQgRGF0YQoKZGZfbm9kdXAgPC0gZmllbGRfZGF0YSAlPiUKICBncm91cF9ieShUYWcsIFN0ZW1UYWcpICU+JQogIHNsaWNlKDEpICU+JQogIHVuZ3JvdXAoKQoKbnJvdyhkZl9ub2R1cCkKZGZfbm9kdXAKCmBgYAoKYGBge3J9CiNGaWx0ZXIgdG8gdGhlIGZpcnN0IHJvdyBwZXIgZ3JvdXAKI05FVyBEYXRhCm5ld19kZl9ub2R1cCA8LSBuZXdfZmllbGRfZGF0YSAlPiUKICBncm91cF9ieShUYWcsIFN0ZW1UYWcpICU+JQogIHNsaWNlKDEpICU+JQogIHVuZ3JvdXAoKQoKbnJvdyhuZXdfZGZfbm9kdXApCm5ld19kZl9ub2R1cApgYGAKCgpgYGB7cn0KI0NoZWNrIGZvciBtaXNzaW5nIHZhbHVlcyBpbiBlYWNoIGNvbHVtbgojT0xEIERhdGEKY29sU3Vtcyhpcy5uYShkZl9ub2R1cCkpCmBgYApgYGB7cn0KI0NoZWNrIGZvciBtaXNzaW5nIHZhbHVlcyBpbiBlYWNoIGNvbHVtbgojTkVXIERhdGEKY29sU3Vtcyhpcy5uYShuZXdfZGZfbm9kdXApKQpgYGAKCmBgYHtyfQojQ2hlY2sgcm93cyB0aGF0IGhhdmUgbnVsbCBEQkggdmFsdWVzCiNPTEQgRGF0YQpEQkhfbmEgPC0gZGZfbm9kdXAgJT4lCiAgZmlsdGVyKGlzLm5hKERCSCkpIApoZWFkKERCSF9uYSkKCmBgYApgYGB7cn0KI0NoZWNrIHJvd3MgdGhhdCBoYXZlIG51bGwgREJIIHZhbHVlcwojTkVXIERhdGEKbmV3X0RCSF9uYSA8LSBuZXdfZGZfbm9kdXAgJT4lCiAgZmlsdGVyKGlzLm5hKERCSCkpIAoKCm5ld19zdGVtdGFnX25hIDwtIG5ld19kZl9ub2R1cCAlPiUKICBmaWx0ZXIoaXMubmEoU3RlbVRhZykpIAoKbmV3X0RCSF9uYQpuZXdfc3RlbXRhZ19uYQoKIyMgTmV3IERhdGEgaGFzIG5vIHN0ZW10YWcgPSAyIHJvd3MgISEhCiMgYW5kIGhhcyBubyBEQkggPSA0IHJvd3MKYGBgCgojQ0xFQU4gREFUQQoKYGBge3J9CiNLZWVwIG9ic2VydmF0aW9ucyB3aXRoIERCSCBwcmVzZW50IGFuZCBEQkgg4omlIDUKI29sZCBkYXRhCmRhdGFfY2xlYW4gPC0gZGZfbm9kdXAgICU+JQogIGZpbHRlcighaXMubmEoREJIKSAmIERCSCA+PSA1KQoKbnJvdyhkYXRhX2NsZWFuKQpoZWFkKGRhdGFfY2xlYW4pCmBgYAoKYGBge3J9CiNLZWVwIG9ic2VydmF0aW9ucyB3aXRoIERCSCBwcmVzZW50IGFuZCBEQkgg4omlIDUgYW5kIFN0ZW10YWcgcHJlc2VudAojbmV3IGRhdGEKCm5ld19kYXRhX2NsZWFuIDwtIG5ld19kZl9ub2R1cCAgJT4lCiAgZmlsdGVyKCFpcy5uYShEQkgpICYgREJIID49IDUgJiAhaXMubmEoU3RlbVRhZykpCgpucm93KG5ld19kYXRhX2NsZWFuKQpoZWFkKG5ld19kYXRhX2NsZWFuKQpgYGAKCiMgVklTVUFMSVpBVElPTgoKYGBge3J9CiMJSWRlbnRpZnkgdGhlIHNwZWNpZXMgaW4gdGhlIGRhdGFzZXQgCiMgT0xEIERBVEEgIwoKc3BlY2llc190cmVlIDwtIGRhdGFfY2xlYW4gJT4lCiAgZ3JvdXBfYnkoR2VudXMuc3BlY2llcykgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAgJT4lCiAgYXJyYW5nZShkZXNjKGNvdW50KSkKCnNwZWNpZXNfdHJlZQoKI25yb3coc3BlY2llc190cmVlKQpgYGAKCmBgYHtyfQojCUlkZW50aWZ5IHRoZSBzcGVjaWVzIGluIHRoZSBkYXRhc2V0IAojIE5ldyBEQVRBICMKCm5ld19zcGVjaWVzX3RyZWUgPC0gbmV3X2RhdGFfY2xlYW4gJT4lCiAgZ3JvdXBfYnkoR2VudXNfc3BlY2llcykgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAgJT4lCiAgYXJyYW5nZShkZXNjKGNvdW50KSkKCm5ld19zcGVjaWVzX3RyZWUKCiNucm93KHNwZWNpZXNfdHJlZSkKYGBgCgpgYGB7cn0KI09MRCBEQVRBCiMgMSkg4LiZ4Lix4Lia4LiI4Liz4LiZ4Lin4LiZ4LiB4Li04LmI4LiH4LiV4LmI4LitICLguJXguYnguJkiCnN0ZW1fY291bnQgPC0gZGF0YV9jbGVhbiAlPiUKICBncm91cF9ieShUYWcsIEdlbnVzLnNwZWNpZXMpICU+JQogIHN1bW1hcmlzZShuX3N0ZW1zID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKQoKIyAyKSDguYDguKXguLfguK3guIHguYDguInguJ7guLLguLDguJXguYnguJnguJfguLXguYjguYHguJXguIHguIHguLTguYjguIcgKOC4oeC4teC4oeC4suC4geC4geC4p+C5iOC4siAxIOC4geC4tOC5iOC4hykKbXVsdGlfc3RlbSA8LSBzdGVtX2NvdW50ICU+JQogIGZpbHRlcihuX3N0ZW1zID4gMSkKCiMgMykg4LiZ4Lix4Lia4LiI4Liz4LiZ4Lin4LiZICLguJXguYnguJnguJfguLXguYjguYHguJXguIHguIHguLTguYjguIciIOC4leC5iOC4rSBzcGVjaWVzCnNwZWNpZXNfbXVsdGlfY291bnQgPC0gbXVsdGlfc3RlbSAlPiUKICBjb3VudChHZW51cy5zcGVjaWVzLCBzb3J0ID0gVFJVRSkKICAjICU+JQogICNzbGljZV9tYXgobiwgbiA9IDEyKQpzcGVjaWVzX211bHRpX2NvdW50CmBgYApgYGB7cn0KI09MRCBEQVRBCnNwZWNpZXNfbXVsdGlfY291bnQgPC0gZGF0YV9jbGVhbiAlPiUKICBncm91cF9ieShUYWcsIEdlbnVzLnNwZWNpZXMpICU+JQogIHN1bW1hcmlzZShuX3N0ZW1zID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICBmaWx0ZXIobl9zdGVtcyA+IDEpICU+JQogIGNvdW50KEdlbnVzLnNwZWNpZXMsIHNvcnQgPSBUUlVFKSAKICAjJT4lICBzbGljZV9tYXgobiwgbiA9IDEyKQpgYGAKCmBgYHtyfQpzcGVjaWVzX211bHRpX2NvdW50CmBgYAoKCmBgYHtyfQoKZ2dwbG90KHNwZWNpZXNfbXVsdGlfY291bnQsIGFlcyh4ID0gcmVvcmRlcihHZW51cy5zcGVjaWVzLCBuKSwgeSA9IG4pKSArCiAgZ2VvbV9jb2woZmlsbCA9ICIjMjZDNEI4IikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIk51bWJlciBvZiBNdWx0aS1zdGVtIFRyZWVzIGJ5IFNwZWNpZXMiLAogICAgeCA9ICJTcGVjaWVzIiwKICAgIHkgPSAiTnVtYmVyIG9mIE11bHRpLXN0ZW0gVHJlZXMiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikKYGBgCmBgYHtyfQojIDEpIOC4q+C4siBUb3AgMTIgc3BlY2llcyAo4LiB4Lix4LiZ4LiL4LmJ4Liz4Lij4Liy4Lii4LiV4LmJ4LiZ4LiB4LmI4Lit4LiZKQp0b3AxMl9zcGVjaWVzIDwtIGRhdGFfY2xlYW4gJT4lCiAgZGlzdGluY3QoVGFnLCBHZW51cy5zcGVjaWVzKSAlPiUKICBjb3VudChHZW51cy5zcGVjaWVzLCBzb3J0ID0gVFJVRSkgJT4lCiAgc2xpY2VfbWF4KG4sIG4gPSAxMikKCiMgMikgUGxvdCBiYXIgY2hhcnQKZ2dwbG90KHRvcDEyX3NwZWNpZXMsIGFlcyh4ID0gcmVvcmRlcihHZW51cy5zcGVjaWVzLCBuKSwgeSA9IG4pKSArCiAgZ2VvbV9jb2woZmlsbCA9ICIjMjZDNEI4IikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCAxMiBTcGVjaWVzIGJ5IE51bWJlciBvZiBUcmVlcyIsCiAgICB4ID0gIlNwZWNpZXMiLAogICAgeSA9ICJOdW1iZXIgb2YgVHJlZXMiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikKYGBgCgoKYGBge3J9CiNORVcgREFUQQojIDEpIOC4meC4seC4muC4iOC4s+C4meC4p+C4meC4geC4tOC5iOC4h+C4leC5iOC4rSAi4LiV4LmJ4LiZIgpuZXdfc3RlbV9jb3VudCA8LSBuZXdfZGF0YV9jbGVhbiAlPiUKICBncm91cF9ieShUYWcsIEdlbnVzX3NwZWNpZXMpICU+JQogIHN1bW1hcmlzZShuX3N0ZW1zID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKQoKIyAyKSDguYDguKXguLfguK3guIHguYDguInguJ7guLLguLDguJXguYnguJnguJfguLXguYjguYHguJXguIHguIHguLTguYjguIcgKOC4oeC4teC4oeC4suC4geC4geC4p+C5iOC4siAxIOC4geC4tOC5iOC4hykKbmV3X211bHRpX3N0ZW0gPC0gbmV3X3N0ZW1fY291bnQgJT4lCiAgZmlsdGVyKG5fc3RlbXMgPiAxKQoKIyAzKSDguJnguLHguJrguIjguLPguJnguKfguJkgIuC4leC5ieC4meC4l+C4teC5iOC5geC4leC4geC4geC4tOC5iOC4hyIg4LiV4LmI4LitIHNwZWNpZXMKbmV3X3NwZWNpZXNfbXVsdGlfY291bnQgPC0gbmV3X211bHRpX3N0ZW0gJT4lCiAgY291bnQoR2VudXNfc3BlY2llcywgc29ydCA9IFRSVUUpCgpuZXdfc3BlY2llc19tdWx0aV9jb3VudApgYGAKCmBgYHtyfQojTkVXIERBVEEKbmV3X3NwZWNpZXNfbXVsdGlfY291bnQgPC0gbmV3X2RhdGFfY2xlYW4gJT4lCiAgZ3JvdXBfYnkoVGFnLCBHZW51c19zcGVjaWVzKSAlPiUKICBzdW1tYXJpc2Uobl9zdGVtcyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgZmlsdGVyKG5fc3RlbXMgPiAxKSAlPiUKICBjb3VudChHZW51c19zcGVjaWVzLCBzb3J0ID0gVFJVRSkKICAjICU+JSBzbGljZV9tYXgobiwgbiA9IDEyKQpuZXdfc3BlY2llc19tdWx0aV9jb3VudApgYGAKCmBgYHtyfQojIOC5g+C4quC5iCBsYWJlbCDguKfguYjguLLguYDguJvguYfguJkgT2xkIOC4q+C4o+C4t+C4rSBOZXcKc3BlY2llc19tdWx0aV9jb3VudCA8LSBzcGVjaWVzX211bHRpX2NvdW50ICU+JQogIG11dGF0ZShTb3VyY2UgPSAiT2xkIikKCm5ld19zcGVjaWVzX211bHRpX2NvdW50IDwtIG5ld19zcGVjaWVzX211bHRpX2NvdW50ICU+JQogIG11dGF0ZShTb3VyY2UgPSAiTmV3IikKCiMg4Lij4Lin4Lih4LiV4Liy4Lij4Liy4LiHCmNvbWJpbmVkX211bHRpX2NvdW50IDwtIGJpbmRfcm93cygKICBzcGVjaWVzX211bHRpX2NvdW50ICU+JSByZW5hbWUoU3BlY2llcyA9IEdlbnVzLnNwZWNpZXMpLAogIG5ld19zcGVjaWVzX211bHRpX2NvdW50ICU+JSByZW5hbWUoU3BlY2llcyA9IEdlbnVzX3NwZWNpZXMpCikKCgoKYGBgCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHN0cmluZ3IpCgojIDApIOC4l+C4s+C4hOC4p+C4suC4oeC4quC4sOC4reC4suC4lOC4iuC4t+C5iOC4reC4quC4m+C4teC4iuC4teC4quC5jOC4geC4seC4meC4geC4o+C4k+C4teC5gOC4p+C5ieC4meC4p+C4o+C4o+C4hC/guKPguLnguJvguYHguJrguJrguJXguYjguLLguIfguIHguLHguJkKY29tYmluZWRfbXVsdGlfY291bnQgPC0gY29tYmluZWRfbXVsdGlfY291bnQgJT4lCiAgbXV0YXRlKFNwZWNpZXMgPSBzdHJfc3F1aXNoKFNwZWNpZXMpKQoKIyAxKSDguKvguLIgVG9wIDEyIOC4iOC4suC4geC4nOC4peC4o+C4p+C4oSAoT2xkICsgTmV3KQp0b3AxMl9zcGVjaWVzIDwtIGNvbWJpbmVkX211bHRpX2NvdW50ICU+JQogIGdyb3VwX2J5KFNwZWNpZXMpICU+JQogIHN1bW1hcmlzZShUb3RhbCA9IHN1bShuLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICBhcnJhbmdlKGRlc2MoVG90YWwpKSAlPiUKICBzbGljZV9oZWFkKG4gPSAxMikgJT4lCiAgcHVsbChTcGVjaWVzKQoKIyAyKSDguIHguKPguK3guIfguYDguInguJ7guLLguLAgVG9wIDEyIOC5geC4peC4sOC4geC4s+C4q+C4meC4lOC4peC4s+C4lOC4seC4muC5geC4geC4mSBYIOC4leC4suC4oSBUb3RhbCAo4Lih4Liy4LiBIC0+IOC4meC5ieC4reC4oikKc3BlY2llc19vcmRlciA8LSBjb21iaW5lZF9tdWx0aV9jb3VudCAlPiUKICBncm91cF9ieShTcGVjaWVzKSAlPiUKICBzdW1tYXJpc2UoVG90YWwgPSBzdW0obiwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgZmlsdGVyKFNwZWNpZXMgJWluJSB0b3AxMl9zcGVjaWVzKSAlPiUKICBhcnJhbmdlKGRlc2MoVG90YWwpKSAlPiUKICBwdWxsKFNwZWNpZXMpCgpjb21iaW5lZF90b3AxMiA8LSBjb21iaW5lZF9tdWx0aV9jb3VudCAlPiUKICBmaWx0ZXIoU3BlY2llcyAlaW4lIHRvcDEyX3NwZWNpZXMpICU+JQogIG11dGF0ZShTcGVjaWVzID0gZmFjdG9yKFNwZWNpZXMsIGxldmVscyA9IHNwZWNpZXNfb3JkZXIpKSAlPiUKICAjIDMpIOC5g+C4q+C5ieC5geC4leC5iOC4peC4sOC4quC4m+C4teC4iuC4teC4quC5jOC4oeC4teC4guC5ieC4reC4oeC4ueC4pSBPbGQg4LmB4Lil4LiwIE5ldyDguK3guKLguYjguLLguIfguKXguLAgMSDguYHguJfguYjguIcgKOC4luC5ieC4suC5hOC4oeC5iOC4oeC4tSDguYDguJXguLTguKEgMCkKICBjb21wbGV0ZShTcGVjaWVzLCBTb3VyY2UsIGZpbGwgPSBsaXN0KG4gPSAwKSkKCiMg4LiB4Liz4Lir4LiZ4LiU4Lil4Liz4LiU4Lix4LiaIFNvdXJjZSA9IE9sZCDguIHguYjguK3guJkgTmV3CmNvbWJpbmVkX3RvcDEyIDwtIGNvbWJpbmVkX3RvcDEyICU+JQogIG11dGF0ZShTb3VyY2UgPSBmYWN0b3IoU291cmNlLCBsZXZlbHMgPSBjKCJPbGQiLCAiTmV3IikpKQoKIyBQbG90CmdncGxvdChjb21iaW5lZF90b3AxMiwgYWVzKHggPSBTcGVjaWVzLCB5ID0gbiwgZmlsbCA9IFNvdXJjZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBsYWJzKAogICAgeCA9ICJHZW51c1NwZWNpZXMiLAogICAgeSA9ICJOdW1iZXIgb2YgbXVsdGktc3RlbSB0cmVlcyIsCiAgICB0aXRsZSA9ICJUb3AgMTIgc3BlY2llczogT2xkIHZzIE5ldyAobXVsdGktc3RlbSBjb3VudCkiCiAgKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIKICApCgpgYGAKYGBge3J9CnltYXggPC0gbWF4KGNvbWJpbmVkX3RvcDEyJG4sIG5hLnJtID0gVFJVRSkKCmdncGxvdChjb21iaW5lZF90b3AxMiwgYWVzKHggPSBTcGVjaWVzLCB5ID0gbiwgZmlsbCA9IFNvdXJjZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICBicmVha3MgPSBzZXEoMCwgeW1heCwgYnkgPSA1MCksICAgICAgIyDguIHguLPguKvguJnguJTguIrguYjguKfguIfguJfguLjguIEgNTAKICAgIGxhYmVscyA9IHNjYWxlczo6Y29tbWEgICAgICAgICAgICAgICAjIOC5g+C4quC5iCBjb21tYSDguYDguIrguYjguJkgMSwwMDAKICApICsKICBsYWJzKAogICAgeCA9ICJHZW51c1NwZWNpZXMiLAogICAgeSA9ICJOdW1iZXIgb2YgbXVsdGktc3RlbSB0cmVlcyIsCiAgICB0aXRsZSA9ICJUb3AgMTIgc3BlY2llczogT2xkIHZzIE5ldyAobXVsdGktc3RlbSBjb3VudCkiCiAgKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIKICApCmBgYAoKCgpgYGB7cn0KIwlCYXIgcGxvdCBvZiB0b3RhbCB0cmVlIGNvdW50cyBieSBzcGVjaWVzCiMgT0xEIGRhdGEKCmdncGxvdChzcGVjaWVzX3RyZWUsIGFlcyh4ID0gcmVvcmRlcihHZW51cy5zcGVjaWVzLCBjb3VudCksIHkgPSBjb3VudCkpICsKICBnZW9tX2NvbChmaWxsID0gInN0ZWVsYmx1ZSIpICsKICBjb29yZF9mbGlwKCkgKyAgIyBmbGlwIHRoZSBheGlzCiAgbGFicyh0aXRsZSA9ICJUcmVlIGNvdW50IGJ5IHNwZWNpZXMgIiwKICAgICAgIHggPSAiR2VudXNTcGVjaWVzIiwKICAgICAgIHkgPSAibnVtYmVyIG9mIHRyZWUiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9CiMJQmFyIHBsb3Qgb2YgdG90YWwgdHJlZSBjb3VudHMgYnkgc3BlY2llcwojIE5ldyBkYXRhCgpnZ3Bsb3QobmV3X3NwZWNpZXNfdHJlZSwgYWVzKHggPSByZW9yZGVyKEdlbnVzX3NwZWNpZXMsIGNvdW50KSwgeSA9IGNvdW50KSkgKwogIGdlb21fY29sKGZpbGwgPSAic3RlZWxibHVlIikgKwogIGNvb3JkX2ZsaXAoKSArICAjIGZsaXAgdGhlIGF4aXMKICBsYWJzKHRpdGxlID0gIlRyZWUgY291bnQgYnkgc3BlY2llcyAiLAogICAgICAgeCA9ICJHZW51c1NwZWNpZXMiLAogICAgICAgeSA9ICJudW1iZXIgb2YgdHJlZSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgoKCmBgYHtyfQojQmFyIHBsb3Qgb2YgdGhlIDEyIG1vc3QgYWJ1bmRhbnQgc3BlY2llcyAKI09MRCBkYXRhCgp0b3AxMiA8LSBzcGVjaWVzX3RyZWUgJT4lIHNsaWNlX2hlYWQobiA9IDEyKQoKZ2dwbG90KHRvcDEyLCBhZXMoeCA9IHJlb3JkZXIoR2VudXMuc3BlY2llcywgY291bnQpLCB5ID0gY291bnQpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJmb3Jlc3RncmVlbiIpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnModGl0bGUgPSAiVG9wIDEyIE1vc3QgY29tbW9uIEdlbnVzU3BlY2llcyBPTEQgZGF0YSAiLAogICAgICAgeCA9ICJHZW51c1NwZWNpZXMiLAogICAgICAgeSA9ICJudW1iZXIgb2YgdHJlZSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KI0JhciBwbG90IG9mIHRoZSAxMiBtb3N0IGFidW5kYW50IHNwZWNpZXMgCiNOZXcgRGF0YQoKdG9wMTIgPC0gbmV3X3NwZWNpZXNfdHJlZSAlPiUgc2xpY2VfaGVhZChuID0gMTIpCgpnZ3Bsb3QodG9wMTIsIGFlcyh4ID0gcmVvcmRlcihHZW51c19zcGVjaWVzLCBjb3VudCksIHkgPSBjb3VudCkpICsKICBnZW9tX2NvbChmaWxsID0gImZvcmVzdGdyZWVuIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh0aXRsZSA9ICJUb3AgMTIgTW9zdCBjb21tb24gR2VudXNTcGVjaWVzIE5ldyBEYXRhIiwKICAgICAgIHggPSAiR2VudXNTcGVjaWVzIiwKICAgICAgIHkgPSAibnVtYmVyIG9mIHRyZWUiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKCiMgREJIIERpc3RyaWJ1dGlvbiBieSBzcGVjaWVzCgojIERCSCBmb3IgdHJlZSBsZXZlbAoKYGBge3J9CiNDYWxjdWxhdGUgdHJlZS1sZXZlbCBEQkgKIyBPTEQgZGF0YQpkYmhfdHJlZSA8LSBkYXRhX2NsZWFuICU+JQogIGZpbHRlcighaXMubmEoREJIKSkgJT4lICAgICAgICAgICAgIAogIGdyb3VwX2J5KFRhZywgR2VudXMuc3BlY2llcykgJT4lICAgICAKICBzdW1tYXJpc2UoREJIX3RyZWUgPSBzcXJ0KHN1bShEQkheMikpLCAuZ3JvdXBzID0gImRyb3AiKQoKYGBgCgpgYGB7cn0KZGJoX3RyZWUKYGBgCgoKYGBge3J9CiNDYWxjdWxhdGUgdHJlZS1sZXZlbCBEQkgKIyBOZXcgZGF0YQpuZXdfZGJoX3RyZWUgPC0gbmV3X2RhdGFfY2xlYW4gJT4lCiAgZmlsdGVyKCFpcy5uYShEQkgpKSAlPiUgICAgICAgICAgICAgCiAgZ3JvdXBfYnkoVGFnLCBHZW51c19zcGVjaWVzKSAlPiUgICAgIAogIHN1bW1hcmlzZShEQkhfdHJlZSA9IHNxcnQoc3VtKERCSF4yKSksIC5ncm91cHMgPSAiZHJvcCIpCmBgYAoKYGBge3J9Cm5ld19kYmhfdHJlZQpgYGAKCgoKYGBge3J9CiMgT0xEIGRhdGEKIyBQcmVwYXJlIGEgbGlzdCBvZiB0aGUgdG9wIDEyIHNwZWNpZXMgYXQgdGhlIHRyZWUgbGV2ZWwKZGlzdHJpYnV0aW9uX3NwZWNpZXNfdHJlZSA8LSBkYmhfdHJlZSAlPiUKICBjb3VudChHZW51cy5zcGVjaWVzLCBzb3J0ID0gVFJVRSkgJT4lCiAgc2xpY2VfbWF4KG4sIG4gPSAxMikgJT4lCiAgcHVsbChHZW51cy5zcGVjaWVzKQoKIyBBcnJhbmdlIHNwZWNpZXMgaW4gYXNjZW5kaW5nIG9yZGVyIG9mIGFidW5kYW5jZQpzcGVjaWVzX29yZGVyX3RyZWUgPC0gZGJoX3RyZWUgJT4lCiAgY291bnQoR2VudXMuc3BlY2llcywgc29ydCA9IFRSVUUpICU+JQogIGZpbHRlcihHZW51cy5zcGVjaWVzICVpbiUgZGlzdHJpYnV0aW9uX3NwZWNpZXNfdHJlZSkgJT4lCiAgcHVsbChHZW51cy5zcGVjaWVzKSAgJT4lCiAgcmV2KCkKCiMgYm94cGxvdCAodHJlZSBsZXZlbCkKZ2dwbG90KAogIGRiaF90cmVlICU+JQogICAgZmlsdGVyKEdlbnVzLnNwZWNpZXMgJWluJSBkaXN0cmlidXRpb25fc3BlY2llc190cmVlKSAlPiUKICAgIG11dGF0ZShHZW51cy5zcGVjaWVzID0gZmFjdG9yKEdlbnVzLnNwZWNpZXMsIGxldmVscyA9IHNwZWNpZXNfb3JkZXJfdHJlZSkpLAogIGFlcyh4ID0gR2VudXMuc3BlY2llcywgeSA9IERCSF90cmVlKQopICsKICBnZW9tX2JveHBsb3QoZmlsbCA9ICIjMjZDNEI4Iiwgb3V0bGllci5jb2xvciA9ICIjRTZCODAwIiwgb3V0bGllci5zaXplID0gMSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRyZWUtbGV2ZWwgREJIIERpc3RyaWJ1dGlvbiAoVG9wIDEyIFNwZWNpZXMpIE9MRCBEQVRBIiwKICAgIHggPSAiR2VudXNTcGVjaWVzIiwKICAgIHkgPSAiREJIIChjbSkiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikKYGBgCgpgYGB7cn0KIyBOZXcgRGF0YQojIFByZXBhcmUgYSBsaXN0IG9mIHRoZSB0b3AgMTIgc3BlY2llcyBhdCB0aGUgdHJlZSBsZXZlbApkaXN0cmlidXRpb25fbmV3X3NwZWNpZXNfdHJlZSA8LSBuZXdfZGJoX3RyZWUgJT4lCiAgY291bnQoR2VudXNfc3BlY2llcywgc29ydCA9IFRSVUUpICU+JQogIHNsaWNlX21heChuLCBuID0gMTIpICU+JQogIHB1bGwoR2VudXNfc3BlY2llcykKCiMgQXJyYW5nZSBzcGVjaWVzIGluIGFzY2VuZGluZyBvcmRlciBvZiBhYnVuZGFuY2UKbmV3X3NwZWNpZXNfb3JkZXJfdHJlZSA8LSBuZXdfZGJoX3RyZWUgJT4lCiAgY291bnQoR2VudXNfc3BlY2llcywgc29ydCA9IFRSVUUpICU+JQogIGZpbHRlcihHZW51c19zcGVjaWVzICVpbiUgZGlzdHJpYnV0aW9uX25ld19zcGVjaWVzX3RyZWUpICU+JQogIHB1bGwoR2VudXNfc3BlY2llcykgICU+JQogIHJldigpCgojIGJveHBsb3QgKHRyZWUgbGV2ZWwpCmdncGxvdCgKICBuZXdfZGJoX3RyZWUgJT4lCiAgICBmaWx0ZXIoR2VudXNfc3BlY2llcyAlaW4lIGRpc3RyaWJ1dGlvbl9uZXdfc3BlY2llc190cmVlKSAlPiUKICAgIG11dGF0ZShHZW51c19zcGVjaWVzID0gZmFjdG9yKEdlbnVzX3NwZWNpZXMsIGxldmVscyA9IG5ld19zcGVjaWVzX29yZGVyX3RyZWUpKSwKICBhZXMoeCA9IEdlbnVzX3NwZWNpZXMsIHkgPSBEQkhfdHJlZSkKKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAiI0U3NTQ4MCIsIG91dGxpZXIuY29sb3IgPSAiI0U2QjgwMCIsIG91dGxpZXIuc2l6ZSA9IDEpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJUcmVlLWxldmVsIERCSCBEaXN0cmlidXRpb24gKFRvcCAxMiBTcGVjaWVzKSBORVcgREFUQSIsCiAgICB4ID0gIkdlbnVzU3BlY2llcyIsCiAgICB5ID0gIkRCSCAoY20pIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpCmBgYAoKCiMjIERCSCBzdGVtIGxldmVsCgojIE9MRCBkYXRhCgpgYGB7cn0KI1RoZSAxMiBzcGVjaWVzIHdpdGggdGhlIGhpZ2hlc3QgbnVtYmVyIG9mIHRyZWVzIApkaXN0cmlidXRpb25fc3BlY2llc19zdGVtIDwtIGRhdGFfY2xlYW4gJT4lCiAgZGlzdGluY3QoVGFnLCBHZW51cy5zcGVjaWVzKSAlPiUgICAgICAgICAKICBjb3VudChHZW51cy5zcGVjaWVzLCBzb3J0ID0gVFJVRSkgJT4lIAogIHNsaWNlX21heChuLCBuID0gMTIpICU+JSAgIAogIHB1bGwoR2VudXMuc3BlY2llcykKCiMJU2VxdWVuY2Ugb2YgdGhlIDEyIHNwZWNpZXMgZm9yIHBsb3R0aW5nLCBzb3J0ZWQgaW4gYXNjZW5kaW5nIG9yZGVyIG9mIGFidW5kYW5jZQpzcGVjaWVzX29yZGVyX3N0ZW0gPC0gZGF0YV9jbGVhbiAlPiUKICBkaXN0aW5jdChUYWcsIEdlbnVzLnNwZWNpZXMpICU+JQogIGNvdW50KEdlbnVzLnNwZWNpZXMsIHNvcnQgPSBUUlVFKSAlPiUKICBmaWx0ZXIoR2VudXMuc3BlY2llcyAlaW4lIGRpc3RyaWJ1dGlvbl9zcGVjaWVzX3N0ZW0pICU+JQogIHB1bGwoR2VudXMuc3BlY2llcykgJT4lCiAgcmV2KCkKCmBgYAoKCmBgYHtyfQojIEJveCBwbG90ICBmb3IgU3RlbSBsZXZlbAoKZ2dwbG90KAogIGRhdGFfY2xlYW4gJT4lCiAgICBmaWx0ZXIoR2VudXMuc3BlY2llcyAlaW4lIGRpc3RyaWJ1dGlvbl9zcGVjaWVzX3N0ZW0pICU+JQogICAgbXV0YXRlKEdlbnVzLnNwZWNpZXMgPSBmYWN0b3IoR2VudXMuc3BlY2llcywgbGV2ZWxzID0gc3BlY2llc19vcmRlcl9zdGVtKSksCiAgYWVzKHggPSBHZW51cy5zcGVjaWVzLCB5ID0gREJIKQopICsKICBnZW9tX2JveHBsb3QoZmlsbCA9ICIjMjZDNEI4Iiwgb3V0bGllci5jb2xvciA9ICIjRTZCODAwIiwgb3V0bGllci5zaXplID0gMSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlN0ZW0tbGV2ZWwgREJIIERpc3RyaWJ1dGlvbiAoVG9wIDEyIFNwZWNpZXMpIE9MRCBEQVRBIiwKICAgIHggPSAiR2VudXNTcGVjaWVzIiwKICAgIHkgPSAiREJIIChjbSkiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikKYGBgCgojTmV3IGRhdGEKYGBge3J9CiNUaGUgMTIgc3BlY2llcyB3aXRoIHRoZSBoaWdoZXN0IG51bWJlciBvZiB0cmVlcyAKbmV3X2Rpc3RyaWJ1dGlvbl9zcGVjaWVzX3N0ZW0gPC0gbmV3X2RhdGFfY2xlYW4gJT4lCiAgZGlzdGluY3QoVGFnLCBHZW51c19zcGVjaWVzKSAlPiUgICAgICAgICAKICBjb3VudChHZW51c19zcGVjaWVzLCBzb3J0ID0gVFJVRSkgJT4lIAogIHNsaWNlX21heChuLCBuID0gMTIpICU+JSAgIAogIHB1bGwoR2VudXNfc3BlY2llcykKCiMJU2VxdWVuY2Ugb2YgdGhlIDEyIHNwZWNpZXMgZm9yIHBsb3R0aW5nLCBzb3J0ZWQgaW4gYXNjZW5kaW5nIG9yZGVyIG9mIGFidW5kYW5jZQpuZXdfc3BlY2llc19vcmRlcl9zdGVtIDwtIG5ld19kYXRhX2NsZWFuICU+JQogIGRpc3RpbmN0KFRhZywgR2VudXNfc3BlY2llcykgJT4lCiAgY291bnQoR2VudXNfc3BlY2llcywgc29ydCA9IFRSVUUpICU+JQogIGZpbHRlcihHZW51c19zcGVjaWVzICVpbiUgbmV3X2Rpc3RyaWJ1dGlvbl9zcGVjaWVzX3N0ZW0pICU+JQogIHB1bGwoR2VudXNfc3BlY2llcykgJT4lCiAgcmV2KCkKYGBgCgpgYGB7cn0KIyBCb3ggcGxvdCAgZm9yIFN0ZW0gbGV2ZWwKCmdncGxvdCgKICBuZXdfZGF0YV9jbGVhbiAlPiUKICAgIGZpbHRlcihHZW51c19zcGVjaWVzICVpbiUgbmV3X2Rpc3RyaWJ1dGlvbl9zcGVjaWVzX3N0ZW0pICU+JQogICAgbXV0YXRlKEdlbnVzX3NwZWNpZXMgPSBmYWN0b3IoR2VudXNfc3BlY2llcywgbGV2ZWxzID0gbmV3X3NwZWNpZXNfb3JkZXJfc3RlbSkpLAogIGFlcyh4ID0gR2VudXNfc3BlY2llcywgeSA9IERCSCkKKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAiI0U3NTQ4MCIsIG91dGxpZXIuY29sb3IgPSAiI0U2QjgwMCIsIG91dGxpZXIuc2l6ZSA9IDEpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJTdGVtLWxldmVsIERCSCBEaXN0cmlidXRpb24gKFRvcCAxMiBTcGVjaWVzKSBORVcgREFUQSIsCiAgICB4ID0gIkdlbnVzU3BlY2llcyIsCiAgICB5ID0gIkRCSCAoY20pIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpCmBgYAoKCgoKYGBge3J9CiNEZW5zaXR5IHBsb3Qgb2YgREJIIGJ5IFRyZWUtbGV2ZWwKI09MRCBkYXRhCnNwZWNpZXNfb3JkZXJfdHJlZSA8LSBkYmhfdHJlZSAlPiUKICBjb3VudChHZW51cy5zcGVjaWVzLCBzb3J0ID0gVFJVRSkgJT4lCiAgc2xpY2VfbWF4KG4sIG4gPSAxMikgJT4lCiAgcHVsbChHZW51cy5zcGVjaWVzKQoKZ2dwbG90KAogIGRiaF90cmVlICU+JQogICAgZmlsdGVyKEdlbnVzLnNwZWNpZXMgJWluJSBzcGVjaWVzX29yZGVyX3RyZWUpICU+JQogICAgbXV0YXRlKEdlbnVzLnNwZWNpZXMgPSBmYWN0b3IoR2VudXMuc3BlY2llcywgbGV2ZWxzID0gc3BlY2llc19vcmRlcl90cmVlKSksCiAgYWVzKHggPSBEQkhfdHJlZSkKKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAiIzI2QzRCOCIsIGFscGhhID0gMC42KSArCiAgZmFjZXRfd3JhcCh+IEdlbnVzLnNwZWNpZXMsIHNjYWxlcyA9ICJmcmVlIikgKyAKICBsYWJzKHRpdGxlID0gIlRyZWUtbGV2ZWwgREJIIERlbnNpdHkgKFRvcCAxMiBTcGVjaWVzKSBPTEQgREFUQSIsCiAgICAgICB4ID0gIiBEQkggKGNtKSIsIHkgPSAiRGVuc2l0eSIpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKYGBgCgpgYGB7cn0KI0RlbnNpdHkgcGxvdCBvZiBEQkggYnkgVHJlZS1sZXZlbAojTkVXIGRhdGEKbmV3X3NwZWNpZXNfb3JkZXJfdHJlZSA8LSBuZXdfZGJoX3RyZWUgJT4lCiAgY291bnQoR2VudXNfc3BlY2llcywgc29ydCA9IFRSVUUpICU+JQogIHNsaWNlX21heChuLCBuID0gMTIpICU+JQogIHB1bGwoR2VudXNfc3BlY2llcykKCmdncGxvdCgKICBuZXdfZGJoX3RyZWUgJT4lCiAgICBmaWx0ZXIoR2VudXNfc3BlY2llcyAlaW4lIG5ld19zcGVjaWVzX29yZGVyX3RyZWUpICU+JQogICAgbXV0YXRlKEdlbnVzX3NwZWNpZXMgPSBmYWN0b3IoR2VudXNfc3BlY2llcywgbGV2ZWxzID0gbmV3X3NwZWNpZXNfb3JkZXJfdHJlZSkpLAogIGFlcyh4ID0gREJIX3RyZWUpCikgKwogIGdlb21fZGVuc2l0eShmaWxsID0gIiNFNzU0ODAiLCBhbHBoYSA9IDAuNikgKwogIGZhY2V0X3dyYXAofiBHZW51c19zcGVjaWVzLCBzY2FsZXMgPSAiZnJlZSIpICsgCiAgbGFicyh0aXRsZSA9ICJUcmVlLWxldmVsIERCSCBEZW5zaXR5IChUb3AgMTIgU3BlY2llcykgTkVXIERBVEEiLAogICAgICAgeCA9ICIgREJIIChjbSkiLCB5ID0gIkRlbnNpdHkiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgoKYGBge3J9CiNEZW5zaXR5IHBsb3Qgb2YgREJIIGJ5IFN0ZW0tbGV2ZWwKI09MRCBkYXRhCnNwZWNpZXNfb3JkZXJfc3RlbSA8LSBkYXRhX2NsZWFuICU+JQogIGRpc3RpbmN0KFRhZywgR2VudXMuc3BlY2llcykgJT4lCiAgY291bnQoR2VudXMuc3BlY2llcywgc29ydCA9IFRSVUUpICU+JQogIGZpbHRlcihHZW51cy5zcGVjaWVzICVpbiUgZGlzdHJpYnV0aW9uX3NwZWNpZXNfc3RlbSkgJT4lCiAgcHVsbChHZW51cy5zcGVjaWVzKQoKCmdncGxvdCgKICBkYXRhX2NsZWFuICU+JQogICAgZmlsdGVyKEdlbnVzLnNwZWNpZXMgJWluJSBkaXN0cmlidXRpb25fc3BlY2llc19zdGVtKSAlPiUKICAgIG11dGF0ZShHZW51cy5zcGVjaWVzID0gZmFjdG9yKEdlbnVzLnNwZWNpZXMsIGxldmVscyA9IHNwZWNpZXNfb3JkZXJfc3RlbSkpLAogIGFlcyh4ID0gREJILCBmaWxsID0gR2VudXMuc3BlY2llcykKKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAiIzI2QzRCOCIsIGFscGhhID0gMC42KSArCiAgZmFjZXRfd3JhcCh+IEdlbnVzLnNwZWNpZXMsIHNjYWxlcyA9ICJmcmVlIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJTdGVtLWxldmVsIERCSCBEZW5zaXR5IChUb3AgMTIgU3BlY2llcykgT0xEIERBVEEiLAogICAgeCA9ICJEQkggKGNtKSIsCiAgICB5ID0gIkRlbnNpdHkiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmBgYAoKYGBge3J9CiNEZW5zaXR5IHBsb3Qgb2YgREJIIGJ5IFN0ZW0tbGV2ZWwKI05FVyBkYXRhCm5ld19zcGVjaWVzX29yZGVyX3RyZWUgPC0gbmV3X2RhdGFfY2xlYW4gJT4lCiAgZGlzdGluY3QoVGFnLCBHZW51c19zcGVjaWVzKSAlPiUKICBjb3VudChHZW51c19zcGVjaWVzLCBzb3J0ID0gVFJVRSkgJT4lCiAgZmlsdGVyKEdlbnVzX3NwZWNpZXMgJWluJSBkaXN0cmlidXRpb25fbmV3X3NwZWNpZXNfdHJlZSkgJT4lCiAgcHVsbChHZW51c19zcGVjaWVzKQoKCmdncGxvdCgKICBuZXdfZGF0YV9jbGVhbiAlPiUKICAgIGZpbHRlcihHZW51c19zcGVjaWVzICVpbiUgZGlzdHJpYnV0aW9uX25ld19zcGVjaWVzX3RyZWUpICU+JQogICAgbXV0YXRlKEdlbnVzX3NwZWNpZXMgPSBmYWN0b3IoR2VudXNfc3BlY2llcywgbGV2ZWxzID0gbmV3X3NwZWNpZXNfb3JkZXJfdHJlZSkpLAogIGFlcyh4ID0gREJILCBmaWxsID0gR2VudXNfc3BlY2llcykKKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAiI0U3NTQ4MCIsIGFscGhhID0gMC42KSArCiAgZmFjZXRfd3JhcCh+IEdlbnVzX3NwZWNpZXMsIHNjYWxlcyA9ICJmcmVlIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJTdGVtLWxldmVsIERCSCBEZW5zaXR5IChUb3AgMTIgU3BlY2llcykgTkVXIERBVEEiLAogICAgeCA9ICJEQkggKGNtKSIsCiAgICB5ID0gIkRlbnNpdHkiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgoK